package org.rkuk.kasutil.test.system.stack 
{
	import flash.utils.Dictionary;
	import org.rkuk.kasutil.test.event.HandlerEvent;
	import org.rkuk.kasutil.test.system.handler.Handler;
	import org.rkuk.kasutil.test.system.TestThread;
	
	/**
	 * ...
	 * @author rkuk
	 */
	public class OrdinalHandlerStack extends HandlerStack 
	{
		private var handlerStarted_:Dictionary;
		private var handlerBuffer_:Array;
		
		public function OrdinalHandlerStack(testThread:TestThread) 
		{
			super(testThread);
		}
		
		override public function clearBuffer():void 
		{
			if (handlerBuffer_ != null)
			{
				while (handlerBuffer_.length > 0)
					disposeHandler(handlerBuffer_.shift());
			}
		}
		
		override public function pushHandler(handler:Handler):void 
		{
			if (handler != null)
			{
				if (handlerBuffer_ == null)
				{
					handlerBuffer_ = new Array();
					handlerStarted_ = new Dictionary(false);
				}
					
				handlerBuffer_.push(handler);
				handler.addEventListener(HandlerEvent.HANDLER_TRIGGER, onHandlerEvent);
				handler.addEventListener(HandlerEvent.HANDLER_CANCEL, onHandlerEvent);
			}
		}
		
		override public function startHandlerInBuffer():void 
		{
			if (handlerBuffer_ != null)
			{
				while (handlerBuffer_.length > 0)
				{
					//start handler in ordinal sequence, namely first push first start
					var handler:Handler = handlerBuffer_.shift();
					handlerStarted_[handler] = true;
					handler.start();
				}
			}
		}
		
		private function onHandlerEvent(e:HandlerEvent):void 
		{
			var handler:Handler = e.target as Handler;
			disposeHandler(handler);
			
			if (e.type == HandlerEvent.HANDLER_TRIGGER)
				popHandler(handler);
		}
		
		override public function dispose():void 
		{
			clearBuffer();
			for (var handler:Handler in handlerStarted_)
				disposeHandler(handler);
		}
		
		/**
		 * stop the handler, remove listen to the handler and remove its only reference
		 * @param	handler
		 */
		private function disposeHandler(handler:Handler):void 
		{
			handler.removeEventListener(HandlerEvent.HANDLER_TRIGGER, onHandlerEvent);
			handler.addEventListener(HandlerEvent.HANDLER_CANCEL, onHandlerEvent);
			handler.stop();
			
			if (handler in handlerStarted_)
				delete handlerStarted_[handler];
			else
			{
				var index:int = handlerBuffer_.indexOf(handler);
				if(index!=-1)
					handlerBuffer_.splice(index, 1);
			}
		}
	}

}